<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>自定义魔方</title>
</head>
<style>
  *{
    padding: 0;
    margin: 0;
  }
  .cube{
    position: relative;
    margin: 100px auto;
    width: 750px;
    height: 750px;
    background:#f8f8f8;
    display: flex;
    flex-direction: column;
    border-top:1px  solid #e5e5e5;
    border-right:1px  solid #e5e5e5;
    box-sizing: border-box;
  }
  .cube .list{
      display: flex;
      flex:1;
      box-sizing: border-box;
  }
  .cube .list .item{
  
    flex:1;
    border-bottom:1px  solid #e5e5e5;
    border-left:1px  solid #e5e5e5;

    display: flex;
    justify-content:center;
    align-items: center;
    box-sizing: border-box;
  }
  .cube .list .item.active{
    background: #e0edff;
  }
  .cube-selected{
    left: 0;
    top: 0;
    /* width: 300px;
    height: 300px; */
    background:#fff;
    position: absolute;
    z-index: 2;
    border: 1px solid #ebedf0;
    color: #7d7e80;
    box-sizing: border-box;
    cursor: pointer;
  }
  .cube-selected-click:hover .right-delete{
    display: block;
  }
  .cube-selected .right-delete{
    cursor: pointer;
    position: absolute;
    right: -10px;
    top:-10px;
    z-index: 4;
    display: none;
    
  }
  .cube-selected .right-delete img{
    width: 20px;
    height: 20px;
  }
  .cube-selected-click{
    left: 0;
    top: 0;
    border: 1px solid #155bd4;
    color: #155bd4;
    background:#e0edff;
    cursor: default;
    z-index: 3;
  }
  .cube-selected-text{
    font-size: 12px;
    width: 100%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
    text-align: center;
  }
</style>
<body>
    <div class="cube"></div>
    <button class="toall">获取选中的结果</button>
    <button class="toselect">获取渲染的区域的结果</button>

</body>
<script src="./index.js"></script>
<script>
   (()=>{
      class Cube {
        list = []
        current = 1
        // 定义横纵坐标(长宽)
        add(item){
          if(!item) return;
          item.id = this.current;
          item.current = true;
          this.list = this.list.map(item => {
            item.current = false 
            return item;
          });
          this.list.push(item);
          this.current++;
          return item;
        }
        remove(id)
        {
          let index = this.list.findIndex(item => item.id == id);
          if(index >=0)
          {
            return this.list.splice(index,1);
          }else{
            return false;
          }
        }
        clear()
        {
          this.list.clear();
        }
        update(id,item = {})
        {
          let index = this.list.findIndex(c_item => c_item.id == id);
          if(index >=0)
          {
            let citem = this.list[index];
            let newitem = Object.assign({},citem,item)
         
            if(newitem.current == true)
            {
              this.list = this.list.map(item => {
                item.current = false 
                return item;
              })
            }
            return this.list.splice(index,1,newitem);
          }else{
            return false;
          }
        }
        init(list = [])
        {
            this.list = list;
        }
      }
      class DrawCube {
          // 份数 例如 3*3
          options = {
            x:4,
            y:4
          }
          cubeItemX = 0 // 单个模块的长度
          cubeItemY = 0 // 单个模块的宽度
          
          constructor()
          {
            this.cube = new Cube();
          }
          // 选择器
          init(selector,options = {})
          {
            this.options = Object.assign({},this.options,options);
            
            let {x,y,cube} = this.options;
            // 真实渲染数据
            let clientWidth = (selector.clientWidth+1);
            let clientHeight = (selector.clientHeight+1);
            this.cubeItemX = clientWidth/x;
            this.cubeItemY = clientHeight/y;
           

            // 模拟数据
            this.options.clientWidth = this.options.clientWidth || clientWidth; // 初始化
            this.options.clientHeight = this.options.clientHeight || clientHeight; //初始化
            this.options.cubeItemX = this.options.clientWidth / x;
            this.options.cubeItemY = this.options.clientHeight / x;
            

            // 初始化行数html
            let initContainHtml = this.drawcutelist(x,y);
            this.mountedEl(selector,initContainHtml);
            this.addEventListen(selector);
          }

          addEventListen(selector)
          {
            let drawArea = [],cube=this.cube,cubeItemX = this.cubeItemX,cubeItemY = this.cubeItemY,
            optionsCubeItemX = this.options.cubeItemX,optionsCubeItemY = this.options.cubeItemY;
          // 添加单个模块的事件
            selector.addEventListener('click',function(e){
            let target = e.target;
            if(target.className.includes('item'))
            {
              let x = target.getAttribute('data-x');
              let y = target.getAttribute('data-y');
             
              if(drawArea.length == 1)
              {
                let activeels = selector.querySelectorAll('.item.active');
                if(activeels && activeels.length)
                {
                  var target1 = [...activeels].pop();
                  var x1 = target1.getAttribute('data-x');
                  var y1 = target1.getAttribute('data-y');
                  var target2 = [...activeels].shift();
                  var x2 = target2.getAttribute('data-x');
                  var y2 = target2.getAttribute('data-y');
                }
                // target.classList.add("active");
                drawArea = [[x1,y1],[x2,y2]];
                // drawArea.push([x,y]);
                let els = selector.querySelectorAll('.item');
                Array.from(els).map(item => item.classList.remove('active'));
                drawAreaCute(drawArea);
              }else{
                target.classList.add("active");
                drawArea.push([x,y]);
              }
              
            }
          })
          // 区域点坐标
          function areaPointList(startArea,endArea)
          {
              let x0 = ~~startArea[0];
              let y0 = ~~startArea[1];
              let x1 = ~~endArea[0];
              let y1 = ~~endArea[1];
              let maxY = x1 > x0 ? x1 : x0;
              let maxX = y1 > y0 ? y1 : y0;  
              let minY = x1 < x0 ? x1 : x0;
              let minX = y1 < y0 ? y1 : y0; 
              let list = [];
              for (let i = minX; i <= maxX; i++) {
                for (let yi = minY; yi <= maxY; yi++) {
                  list.push(`${i},${yi}`)
                }
              }
              return list;
          }
          // 绘制正方形
          function drawAreaCute(drawArea = []){
              let startdrawArea = drawArea[0];
              let enddrawArea = drawArea[1];
              let x0 = ~~startdrawArea[0];
              let y0 = ~~startdrawArea[1];
              let x1 = ~~enddrawArea[0];
              let y1 = ~~enddrawArea[1];
              let maxY = x1 > x0 ? x1 : x0;
              let maxX = y1 > y0 ? y1 : y0;  
              let minY = x1 < x0 ? x1 : x0;
              let minX = y1 < y0 ? y1 : y0; 
              let currentCube =  cube.add({
                style:{
                  left:minX*cubeItemY,
                  width:Math.round((maxX-minX+1)*cubeItemY),
                  top:minY*cubeItemX,
                  height:Math.round((maxY-minY+1)*cubeItemX)
                },
                showlabel:{
                  width:Math.round((maxX-minX+1)*optionsCubeItemX),
                  height:Math.round((maxY-minY+1)*optionsCubeItemY),
                  top:minY*optionsCubeItemX,
                  left:minX*optionsCubeItemY,
                },
                pointList:[...drawArea],
                className:'cube-selected',
                current:true
              });
              drawArea.length = 0;
              // 清除所有区域选中
              let cubeSelectedEls = selector.querySelectorAll('.cube-selected');
              [...cubeSelectedEls].map(ele => ele.classList.remove('cube-selected-click'));
              // let el = `<div class='cube-selected' style="left:${minX*cubeItemX}px;width:${(maxX-minX+1)*cubeItemX}px;top:${minY*cubeItemX}px;height:${(maxY-minY+1)*cubeItemX}px;"></div>`
              let el = `<div data-id='${currentCube.id}' class='cube-selected cube-selected-click cube-selected-v${currentCube.id}' style="left:${currentCube.style.left}px;width:${currentCube.style.width}px;top:${currentCube.style.top}px;height:${currentCube.style.height}px;">
                <div class="right-delete" data-id="${currentCube.id}">
                  <img src='./img/del_icon.png'>
                </div>  
                <div class="cube-selected-text">${currentCube.showlabel.width}x${currentCube.showlabel.height}像素<div>或同等比例</div></div>
              </div>`
         
              selector.innerHTML += el;             
          }
          // 点击换选中区域
          selector.addEventListener('click',function(e){
             let target = e.path.find(el => {
               if(el.classList)
               {
                return (el.classList).contains('cube-selected')
               }else{
                 return false
               }
             }) || e.target;
             let classList = target.classList;
             if(classList.contains('cube-selected')){
               let id = target.getAttribute('data-id');
               // 清除所有区域选中
              let cubeSelectedEls = selector.querySelectorAll('.cube-selected');
              [...cubeSelectedEls].map(ele => ele.classList.remove('cube-selected-click'));
               target.classList.add('cube-selected-click');
               cube.update(id,{
                 current:true
               });
             }
          },true)
          // 绑定删除绘制区域事件
          selector.addEventListener('click',function(e){
             let paths = e.path;
             let target = paths.find(el => {
                if(el && el.classList)
                {
                  return el.classList.contains('right-delete')
                }else{
                  return false
                }
             }) || e.target;
             let classList = target.classList;
             if(classList.contains('right-delete')){
               let id = target.getAttribute('data-id');
               let cSelector =selector.querySelector('.cube-selected-v'+id);
               cSelector.remove();
               cube.remove(id);
             }
          })
          selector.addEventListener('mouseleave',function(e){
            if(drawArea.length != 1) return false;
            let els = selector.querySelectorAll('.item'),target = e.target;
            Array.from(els).map(item => item.classList.remove('active'));
            drawArea.length = 0;
          })
          selector.addEventListener('mouseover',function(e){
            if(drawArea.length != 1) return false;
            let els = selector.querySelectorAll('.item'),target = e.target;
            if(target.className.includes('item'))
            {
              
              let x = ~~target.getAttribute('data-x');
              let y = ~~target.getAttribute('data-y');
              let x0 = ~~drawArea[0][0];
              let y0 = ~~drawArea[0][1];
              if(cube.list[0])
              {

                let drawPointlist = [];
                // let list = ([].concat.apply([], ));
                cube.list.forEach(item => {
                  drawPointlist.push(...areaPointList(...item.pointList));
                });
                let drawAreaPointList = areaPointList(drawArea[0],[x,y]);
                
                if([...drawPointlist,...drawAreaPointList].length != ([...(new Set([...drawPointlist,...drawAreaPointList]))].length)){
                   return;
                }
              }
              Array.from(els).map(item => item.classList.remove('active'))
              let maxX = x > x0 ? x : x0;
              let maxY = y > y0 ? y : y0;  
              let minX = x < x0 ? x : x0;
              let minY = y < y0 ? y : y0;  
              for (let i = minX; i <= maxX; i++) {
                for (let yi = minY; yi <= maxY; yi++) {
                   Array.from(selector.querySelectorAll(`.item[data-x='${i}'][data-y='${yi}']`)).map(item => item.classList.add('active'));
                }
              }
            }
          })
          }
          // 挂载渲染元素
          mountedEl = (selector,html,isreplace = true) =>
          {
              if(isreplace)
              {
                selector.innerHTML += html;
              }else{
                selector.appendChild(html)
              }
          }
          // 绘制界面
          drawcutelist = (x,y) =>{
            let Els =  "";
          
            for (let i = 0; i < x; i++) {
              let itemEl = "";
              for (let yi = 0; yi < y; yi++) {
                itemEl+=`<div data-x="${i}" data-y="${yi}" class="item"></div>`;
              }
              let listEl = `<div class="list">${itemEl}</div>`;
              Els+=listEl;
            } 
            return Els;
          }
      }

      
      let drawCube =  new DrawCube();
      drawCube.init(document.querySelector('.cube'),{x:7,y:7,clientWidth:777,clientHeight:777});


      document.querySelector('.toall').onclick = function()
      {
          console.log(drawCube.cube);
          console.log(drawCube.cube.list);

      }
      document.querySelector('.toselect').onclick = function()
      {
          console.log(drawCube.cube.list.find(c_item => c_item.current == true));
      }

   })()
</script>
</html>
